#include <gtest/gtest.h>
#include <vtkm/cont/Error.h>
#include <vtkm/cont/ErrorBadType.h>
#include <vtkm/cont/ErrorBadValue.h>


struct MyException : public std::exception
{
  //MyException(const std::string& message)
  //  : _message(message)
  //{
  //}

  template <typename... Args>
  explicit MyException(Args&&... args)
  {

    std::vector<std::string> sub_str{ [&]()
                                      {
                                        std::ostringstream os;
                                        os << args;
                                        return os.str();
                                      }()... };

    std::ostringstream oss;
    for (auto& it = sub_str.begin(); it != sub_str.end(); it++)
    {

      oss << *it << (it == sub_str.end() - 1 ? "" : " ");
    }
    this->_message = oss.str();
  }

  const char* what() const noexcept { return _message.c_str(); }

  const std::string& message() const noexcept { return _message; }

  std::string _message;
};

void Read()
{
  try
  {
    throw MyException("something error,", "error code =", 1);
  }
  catch (const MyException& e)
  {
    EXPECT_EQ((e.message()), "something error, error code = 1");

  }
}

void foo() noexcept
{
  //throw MyException{"ab"};
  //throw std::exception("abc");
}

TEST(exception, 1)
{
  static_assert(noexcept(foo()));
  //EXPECT_TRUE(false);

  foo();

  try
  {
    foo();
  }
  catch (...)
  {
    EXPECT_TRUE(false);
  }
}

TEST(exception, 2)
{
  MyException e("something error", 1);
  EXPECT_EQ((e.message()), "something error 1");
  Read();

}